package thread;

import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: fzykd
 * Date: 2022-10-28
 * Time: 20:41
 */
class MyTask implements Comparable<MyTask> {
    public Runnable runnable;
    public long time;

    public MyTask(Runnable runnable, long after) {
        this.runnable = runnable;
        //传来的相对时间
        this.time = after + System.currentTimeMillis();
    }

    //处理完基本代码之后 最关键的是 这个阻塞队列基于堆实现的 要明确比较策略是什么
    //实现的是Comparable接口 固定写法 注意细节
    public int compareTo(MyTask o) {
        return (int) (this.time - o.time);
    }

    //处理完比较的规则之后 处理一个忙等问题
}

class MyTimer {
    //能有一个数据结构在组织这些任务 带有线程安全的阻塞队列
    PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    Object locker = new Object();


    //写一个方法来布置任务
    public void schedule(Runnable runnable,long time){
        MyTask task = new MyTask(runnable,time);
        queue.put(task);
        //每当有新的任务进队列的时候 都要唤醒那边的阻塞检查一下新的任务时间是否值在最前面的
        synchronized (locker){
            locker.notify();
        }
    }

    //要有一个构造方法 在构造方法当中 要有一个线程不停的区检查是否有时间到了 要去执行的任务
    public MyTimer(){
        Thread t = new Thread(()->{
            while (true){
                try {
                    //从队列中取出
                    MyTask myTask = queue.take();
                    long curTime = System.currentTimeMillis();
                    //和现在的时间比较
                    if (curTime < myTask.time){
                        //说明时间还没到 放回队列当中
                        queue.put(myTask);
                        //当这里时间没到 那么存在一直取出来放回去的忙的操作
                        //应该是当放回去之后 设置一个等待时间
                        synchronized (locker){
                            locker.wait(myTask.time-curTime);
                        }
                    }else {
                        //时间到了就执行
                        myTask.runnable.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}


//实现一个自己版本的定时器
public class Demo4 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        },3000);
    }
}
